package com.auth.config;

import com.ebei.common.bean.config.FilterUrlsPropertiesConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.Resource;

/**

 * */
@Order(100)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //启用方法级的权限认证
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private static final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);


    //通过自定义userDetailsService 来实现查询数据库，手机，二维码等多种验证方式
    /**
     * 获取用户的验证配置类
     */
    @Resource(name = "userDetailService")
    private UserDetailsService userDetailsService;
//    @Bean
//    @Override
//    protected UserDetailsService userDetailsService(){
//        //采用一个自定义的实现UserDetailsService接口的类
//        //return baseUserDetailService;
//        //return new BaseUserDetailService();
//        return new UserDetailsService(){
//            @Override
//            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//                log.info("接收到权限认证username：{}",username);
//                System.out.println("接收到权限认证username："+username);
//                SysUserAuthentication user = null;
//                // 1.真实开发从数据库进行验证用户，以及其对应权限集role
//                // TODO: 2018/12/18
////      // 根据用户名查找系统用户
////        SysUser user = userService.findByUserName(username);
////        if (user != null) {
////            // 根据存在的系统用户查找权限
////            List<Permission> permissions = permissionDao.findByAdminUserId(user.getId());
////            // 构建权限集合
////            List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
////            // 将系统用户数据库菜单权限封装到权限集合
////            for (Permission permission : permissions) {
////                if (permission != null && permission.getName() != null) {
////                    GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName());
////                    // 此处将权限信息添加到 GrantedAuthority 对象中，在后面进行全权限验证时会使用GrantedAuthority 对象。
////                    grantedAuthorities.add(grantedAuthority);
////                }
////            }
////            // 返回userdetails类型User
////            return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
////        } else {
////            throw new UsernameNotFoundException(username + " do not exist!");
////        }
//                //2.以下是测试使用
//                if("admin".equals(username)) {
//                    // IntegrationAuthentication auth = IntegrationAuthenticationContext.get();
//                    //这里可以通过auth 获取 user 值
//                    //然后根据当前登录方式type 然后创建一个sysuserauthentication 重新设置 username 和 password
//                    //比如使用手机验证码登录的， username就是手机号 password就是6位的验证码{noop}000000
//                    //System.out.println(auth);
//                    List<GrantedAuthority> list = AuthorityUtils.createAuthorityList("admin_role"); //所谓的角色，只是增加ROLE_前缀
//                    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//                    user = new SysUserAuthentication("admin",passwordEncoder.encode("123456"),list);
//                }
//
//                //返回UserDetails的实现user不为空，则验证通过
//                return user;
//            }
//        };
//    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        log.info("------请求被WebSecurityConfigurerAdapter 拦截------");
      ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry =
                http.formLogin().loginPage("/authentication/require")
                        .loginProcessingUrl("/authentication/form")
                        .and()
                        .authorizeRequests();

        http
                .authorizeRequests()//定义哪些url需要被保护  哪些不需要保护
                .antMatchers("/oauth/token" , "oauth/check_token").permitAll()//定义这两个链接不需要登录可访问
                 .antMatchers( "/user/**").hasRole("ADMINN" )//任何访问user的需要有ROLE_ADMIN的角色
                .anyRequest().authenticated() //任何没有匹配上的其他的url请求，只需要用户被验证。
                //.antMatchers( "/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
                .and()
                .formLogin().loginPage("/login")//如果未登录则跳转登录的页面   这儿可以控制登录成功和登录失败跳转的页面
                .usernameParameter("username").passwordParameter("password").permitAll()//定义号码与密码的parameter
                .and()
                .csrf().disable();//防止跨站请求  spring security中默认开启
    }

    /**
     * 用户信息验证
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(this.userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    /**
     * Spring Boot 2 配置，这里要bean 注入
     */
    /**
     * Spring Oauth2需要两个认证管理器,这个是客户端认证服务器
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        AuthenticationManager manager = super.authenticationManagerBean();
        return manager;
    }

    /**
     * 加密方式
     */
    @Bean
    PasswordEncoder passwordEncoder() {
       // return PasswordEncoderFactories.createDelegatingPasswordEncoder();
        return new BCryptPasswordEncoder();
    }
}